<?php
/*
 * Author  : top-songshijie
 * Email   : 997031758@qq.com
 * DateTime: 2023/02/22 14:36
 */

namespace SSJ\LaravelHelper\Support;

use Throwable;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Formatter\LineFormatter;
use Illuminate\Database\Events\QueryExecuted;

class Log
{
    /**
     * debug 日志
     *
     * @param $message
     */
    public static function debug($message)
    {
        self::getLogger('debug')->debug(self::builderMessage($message));
    }

    /**
     * info 日志
     *
     * @param $message
     */
    public static function info($message)
    {
        self::getLogger('info')->info(self::builderMessage($message));
    }

    /**
     * sql 日志
     *
     * @param QueryExecuted $event
     */
    public static function sql(QueryExecuted $event)
    {
        $execution_time = $event->time;

        if ($execution_time > 1000) {
            $sql = vsprintf(str_replace("?", "'%s'", $event->sql), $event->bindings);
            self::getLogger('sql')->info(self::builderMessage(['execution_time_ms' => $execution_time, 'sql' => $sql]));
        }
    }

    /**
     * 路由日志
     *
     * @param $data
     */
    public static function router($data)
    {
        $request = request();

        [$method, $path, $execution_time_ms, $param, $ip, $url, $env_name] = [
            $request->method(),
            $request->path(),
            defined('LARAVEL_START') ? ceil((microtime(true) - LARAVEL_START) * 1000) : 0,
            $request->all(),
            $request->getClientIp(),
            $request->url(),
            config('app.name')
        ];

        if (in_array($path, config('laravel-helper.log.router_except_data'))) {
            $data['data'] = 'Not Logged';
        }

        self::getLogger('router')
            ->info(self::builderMessage([
                'env_name'          => $env_name,
                'method'            => $method,
                'path'              => $path,
                'url'               => $url,
                'ip'                => $ip,
                'execution_time_ms' => $execution_time_ms,
                'param'             => $param,
                'data'              => $data,
            ]));
    }

    /**
     * 系统异常日志
     *
     * @param Throwable $throwable
     * @param string    $extra_message
     */
    public static function exception(Throwable $throwable, $extra_message = '')
    {
        /* 所需参数 */
        $request = request();
        [$class, $method, $path, $message, $line, $file, $param, $trace, $ip, $url, $env_name] = [
            get_class($throwable),
            $request->method(),
            $request->path(),
            $throwable->getMessage(),
            $throwable->getLine(),
            $throwable->getFile(),
            $request->all(),
            $throwable->getTraceAsString(),
            $request->getClientIp(),
            $request->url(),
            config('app.name')
        ];
        /* 构造记录信息 */
        $common_message = ['env_name' => $env_name, 'class' => $class, 'method' => $method, 'path' => $path, 'url' => $url, 'ip' => $ip, 'message' => $message, 'line' => $line, 'file' => $file];
        if ($extra_message) {
            $common_message = array_merge($common_message, ['extra_message' => $extra_message]);
        }
        /* 异常日志 */
        self::getLogger('exception')->error(self::builderMessage(array_merge($common_message, ['param' => $param, 'trace' => PHP_EOL . $trace])));

        /* 发送通知 */
        $im_type = config('laravel-helper.im_type');
        if ($im_type == 'work' && config('wechat.work.im.web_hook_key')) {
            $send = true;
        } elseif ($im_type == 'feishu' && config('feishu.im.web_hook_key')) {
            $send = true;
        } else {
            $send = false;
        }
        if ($send) {
            lh_send_im_message('异常告警', array_merge($common_message, ['param' => lh_zh_json_encode($param)]), true);
        }
    }


    /**
     * 获取 monolog 对象
     *
     * @param $name
     *
     * @return Logger
     */
    protected static function getLogger($name)
    {
        $logger = new Logger($name);

        $streamHandler = new StreamHandler(
            storage_path(
                "logs/{$name}/" . date('Y-m-d') . '/' . date('Y-m-d') . '.log'
            )
        );

        $lineFormatter = new LineFormatter('[%datetime%][%channel%]' . '%message%' . "\n", 'Y-m-d H:i:s', true);

        $streamHandler->setFormatter($lineFormatter);

        $logger->pushHandler($streamHandler);

        return $logger;
    }

    /**
     * 构建message
     *
     * @param string|array $message
     *
     * @return string|null
     */
    protected static function builderMessage($message)
    {
        $message = array_merge(['request_trace_id' => request()->headers->get('Request-Trace-Id')], (array)$message);

        return lh_zh_json_encode($message);
    }
}
